using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

using XnaWavPack;
using Microsoft.Xna.Framework.Audio;

namespace XnaWavPackTest
{
	public class TestGame : Microsoft.Xna.Framework.Game
	{
		GraphicsDeviceManager graphics;
		SpriteBatch spriteBatch;

		Texture2D buttonsTexture;

		DynamicSoundEffectInstance musicPlayer;
		WavPackDecoder wavPackDecoder;

		KeyboardState previousKeyboardState;
		GamePadState previousGamePadState;

		const int MAX_SAMPLES = 2205;
		const int CHANNELS = 2;
		byte[] samples = new byte[MAX_SAMPLES * CHANNELS * 2];

		public TestGame()
		{
			graphics = new GraphicsDeviceManager(this);
			graphics.PreferredBackBufferWidth = 1280;
			graphics.PreferredBackBufferHeight = 720;

			Content.RootDirectory = "Content";
		}

		protected override void Initialize()
		{
			base.Initialize();
		}

		protected override void LoadContent()
		{
			spriteBatch = new SpriteBatch(GraphicsDevice);
			musicPlayer = new DynamicSoundEffectInstance(44100, AudioChannels.Stereo);
			musicPlayer.Play();

			buttonsTexture = Content.Load<Texture2D>("Graphics/buttons");
		}

		protected override void UnloadContent()
		{
			musicPlayer.Stop();
			musicPlayer = null;

			if (wavPackDecoder != null)
			{
				wavPackDecoder.Dispose();
				wavPackDecoder = null;
			}
		}

		protected override void Update(GameTime gameTime)
		{
			UpdateInput();
			UpdateMusic();

			base.Update(gameTime);
		}

		void UpdateInput()
		{
			GamePadState currentGamePadState = GamePad.GetState(PlayerIndex.One);
			KeyboardState currentKeyboardState = Keyboard.GetState();

			if (currentKeyboardState.IsKeyDown(Keys.Escape) || currentGamePadState.IsButtonDown(Buttons.Back))
			{
				this.Exit();
			}

			if ((currentKeyboardState.IsKeyDown(Keys.D1) && previousKeyboardState.IsKeyUp(Keys.D1)) ||
				currentGamePadState.IsButtonDown(Buttons.A) && previousGamePadState.IsButtonUp(Buttons.A))
			{
				PlaySong("Content/Songs/Arcadia.wv");
			}
			else if ((currentKeyboardState.IsKeyDown(Keys.D2) && previousKeyboardState.IsKeyUp(Keys.D2)) ||
				currentGamePadState.IsButtonDown(Buttons.B) && previousGamePadState.IsButtonUp(Buttons.B))
			{
				PlaySong("Content/Songs/Circus Tent.wv");
			}
			else if ((currentKeyboardState.IsKeyDown(Keys.D3) && previousKeyboardState.IsKeyUp(Keys.D3)) ||
				currentGamePadState.IsButtonDown(Buttons.X) && previousGamePadState.IsButtonUp(Buttons.X))
			{
				PlaySong("Content/Songs/Heavy Interlude.wv");
			}

			previousKeyboardState = currentKeyboardState;
			previousGamePadState = currentGamePadState;
		}

		void UpdateMusic()
		{
			if (wavPackDecoder != null)
			{
				if (musicPlayer.PendingBufferCount <= 3 && wavPackDecoder.CurrentPosition < wavPackDecoder.SampleCount)
				{
					int samplesReceived = wavPackDecoder.GetSamples(samples, 0, MAX_SAMPLES);
					if (samplesReceived > 0)
					{
						musicPlayer.SubmitBuffer(samples, 0, samplesReceived * CHANNELS * 2);
					}
				}
			}
		}
	

		protected override void Draw(GameTime gameTime)
		{
			GraphicsDevice.Clear(Color.CornflowerBlue);

			spriteBatch.Begin();
			spriteBatch.Draw(buttonsTexture, Vector2.Zero, Color.White);
			spriteBatch.End();

			base.Draw(gameTime);
		}

		void PlaySong(string songPath)
		{
			if (wavPackDecoder != null)
			{
				wavPackDecoder.Dispose();
			}

			wavPackDecoder = new WavPackDecoder(songPath);
			if (wavPackDecoder.SampleRate != 44100 || wavPackDecoder.Channels != CHANNELS)
			{
				// todo: notify of incompatibility
				wavPackDecoder.Dispose();
				wavPackDecoder = null;
			}
		}

		static void Main(string[] args)
		{
			using (TestGame game = new TestGame())
			{
				game.Run();
			}
		}
	}
}
